package com.talent.study.nio;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @Author: hszhou
 * @Date: 2025/4/25 11:47
 * @Description: 必须描述类做什么事情, 实现什么功能
 */
@Slf4j
public class TimerClient {

    public static void main(String[] args) {

        new Thread(  new TimeClientHandler("127.0.0.1",8080)).start();
    }

    public static class TimeClientHandler implements Runnable{

        private String host;

        private int port;

        private Selector selector;

        private SocketChannel socketChannel;

        private volatile boolean stop;

        public TimeClientHandler(String host,int port){
            this.host = host;
            this.port = port;

            try {
                selector = Selector.open();
                socketChannel = SocketChannel.open();
                socketChannel.configureBlocking(false);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        @Override
        public void run() {
            try {
                doConnect();
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }

            while (!stop){
               try {
                    selector.select(1000);
                   Set<SelectionKey> selectionKeys = selector.selectedKeys();
                   Iterator<SelectionKey> iterator = selectionKeys.iterator();
                   SelectionKey key = null;
                   while (iterator.hasNext()){
                       key = iterator.next();
                       iterator.remove();
                       try {
                           handlerInput(key);
                       }catch (Exception e){
                           key.cancel();
                           if(key.channel()!=null){
                               key.channel().close();;
                           }
                       }
                   }
               }catch (Exception e){
                   e.printStackTrace();
               }
           }
           if(selector!=null){
               try{
                   selector.close();
               }catch (IOException e){
                   e.printStackTrace();
               }
           }
        }

        private void handlerInput(SelectionKey key) throws IOException{

            if(key.isValid()){

                SocketChannel channel =(SocketChannel) key.channel();
                if(key.isConnectable()){
                    if(channel.finishConnect()){
                        channel.register(selector,SelectionKey.OP_READ);
                        doWrite(channel);
                    }else{
                        System.exit(1);
                    }
                }
                if(key.isReadable()){

                    ByteBuffer allocate = ByteBuffer.allocate(1024);
                    int read = channel.read(allocate);
                    if(read>0){
                        allocate.flip();
                        byte[] bytes = new byte[read];
                        allocate.get(bytes);
                        String body = new String(bytes);
                        log.info("the time client receive order : {}",body);
                       // this.stop = true;
                    }else if (read<0){
                        key.cancel();
                        channel.close();
                    }else{

                    }
                }
            }
        }

        private void  doConnect() throws IOException{
            if(socketChannel.connect(new InetSocketAddress(host,port))){
                socketChannel.register(selector,SelectionKey.OP_READ);
                doWrite(socketChannel);
            }else{
                socketChannel.register(selector,SelectionKey.OP_CONNECT);
            }
        }


        private void doWrite(SocketChannel sc) throws IOException{

            byte[] req = "QUERY TIME ORDER".getBytes();
            ByteBuffer byteBuffer = ByteBuffer.allocateDirect(req.length);
            byteBuffer.put(req);
            byteBuffer.flip();
            sc.write(byteBuffer);
            if(!byteBuffer.hasRemaining()){
               log.info("send order 2 server succeed");
            }
        }
    }

}
